#include "gd32f30x.h"
#include "string.h"
#include "ESP01.h"
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "BMP280.h"
#include "event_groups.h"

extern EventGroupHandle_t Reconnect_EventGroup_Handle;
extern TaskHandle_t espsend_Handle;
double temp = 26.66;
double pressure = 100005.03;
extern uint8_t light;
extern uint32_t time_open;
uint16_t msgID = 0;
const char *product_id = "L6734nbvzo";

#define OneNet_Post "$sys/L6734nbvzo/xiaoyi/thing/property/post" //设备属性上报请求   发布
#define OneNet_Post_Reply "$sys/L6734nbvzo/xiaoyi/thing/property/post/reply" // 设备属性上报响应  订阅
#define OneNet_Set "$sys/L6734nbvzo/xiaoyi/thing/property/set" //设备属性设置请求  	订阅
#define OneNet_Set_Reply "$sys/L6734nbvzo/xiaoyi/thing/property/set/reply" //设备属性设置响应   发布
#define OneNet_Topic_FROMAT "{\"id\":\"%u\",\"version\":\"1.0\",\"params\":%s}"

uint8_t  pingreq[] = {0xC0,0x00};   //保持连接控制报文

//登录mqtt在esp01s里面
void CONNECT(void)
{

}
//如果登录上去之后想要保持连接但是又没有控制报文发送的话
//就需要每隔一段时间PINGREQ,一直在发送publish报文，所以可以注释
void PINGREQ(void)
{
   //ESP_SendData((char *)pingreq, 2);
}
/// @brief mqtt固定报头的剩余字节转换，低位在前，低位的第八位为1表示后面还有数据长度，高位在后
/// @param re_len 剩余字节长度
/// @param buf 经过转换之后的剩余字节
/// @return 转换之后的剩余字节有多少个字节
uint8_t mqtt_remainbyte_len(uint16_t re_len, uint8_t *buf)
{
    uint8_t ret_len = 0;
    do{
        uint8_t byte = re_len & 0x7F;
        re_len >>= 7;
        if(re_len > 0)
        {
            byte |= 0x80;
        }
        buf[ret_len++] = byte;
    }while(re_len > 0);
    return ret_len;
}
void Publish_Pack(const char * topic, const char *payload)
{
    uint8_t topic_len = strlen(topic);
    uint16_t payload_len = strlen(payload);
    uint16_t remain_len = topic_len + payload_len + 2;
    uint8_t remain_byte[4];
    uint16_t pos = 0;
    uint8_t remain_byte_len = mqtt_remainbyte_len(remain_len, remain_byte);
    uint8_t publish_buf[1024];


    publish_buf[pos++] = 0x30;
    memcpy(&publish_buf[pos], remain_byte, remain_byte_len);
    pos += remain_byte_len;

    publish_buf[pos++] = 0x00;
    publish_buf[pos++] = 0x2A;

    memcpy(&publish_buf[pos], topic, topic_len);
    pos += topic_len;

    memcpy(&publish_buf[pos], payload, payload_len);
    pos += payload_len;

    ESP_SendData((char *)publish_buf, pos);


}
void OnetNet_Post(void)
{
	char para[256];
	char json[256];
	sprintf(para, "{\"temp\":{\"value\":%.2f},\"light\":{\"value\":%d},\"time_open\":{\"value\":%d},\"pressure\":{\"value\":%.2f}}", bmp_gettemp(), light, time_open, bmp_getPress());
	sprintf(json, OneNet_Topic_FROMAT, msgID++, para);

    //发送上报数据
    Publish_Pack(OneNet_Post, json);
    vTaskDelay(800);
}

//每一分钟执行一次，查看是否链接上了mqtt平台
//每次执行的时候都需要把publish报文给挂掉
void Re_connect_Task(void *parameters)
{

    for(;;)
    {
        vTaskDelay(100);
        EventBits_t bittoset = xEventGroupWaitBits(Reconnect_EventGroup_Handle, (EventBits_t)(1 << 3), pdTRUE, pdTRUE, pdMS_TO_TICKS(50));
        if((bittoset & (1 << 3)) == (1 << 3))
        {
            eTaskState send_status = eTaskGetState(espsend_Handle);
            if(send_status != eSuspended)
            {
                vTaskSuspend(espsend_Handle);
            }
            re_checkconnect_mqtt();
        }
        vTaskDelay(20);
    }
}